package com.suray.wcs.service.pojo.rgv.rgv.protocol.message;

import com.suray.basic.wcs.path.core.Node;
import com.suray.basic.wcs.utils.Action;
import com.suray.basic.wcs.utils.LoggerUtil;
import com.suray.wcs.res.enums.MoveOrder;
import com.suray.wcs.res.enums.Order;
import com.suray.wcs.service.pojo.Rgv;
import com.suray.basic.wcs.utils.typedef.Bit;
import com.suray.basic.wcs.utils.typedef.Word;
import com.suray.basic.wcs.utils.typedef.Byte;
import com.suray.wcs.service.pojo.rgv.action.RgvCommandAction;
import com.suray.wcs.service.pojo.rgv.action.RgvTaskAction;
import com.suray.wcs.service.pojo.rgv.action.util.RgvActionStatus;
import com.suray.wcs.service.pojo.rgv.rgv.protocol.base.RgvSendMessage;
import com.suray.wcs.service.pojo.rgv.rgv.protocol.exception.SendMessageException;
import com.suray.wcs.service.pojo.rgv.rgv.protocol.util.RgvMessageType;
import com.suray.wcs.service.pojo.rgv.rgv.protocol.util.RgvTaskMessageType;

import java.util.List;

public class RgvTaskSendMessage extends RgvSendMessage {

    private List<Node> nodes;

    public RgvTaskSendMessage(Rgv rgv, MoveOrder moveOrder, RgvTaskMessageType rgvTaskMessageType) {
        super(rgv, "任务发送");

        this.nodes = moveOrder.getNodeList();
        baseDatas.add(new Word("firstFrame", "报文头帧：02 fd"));
        baseDatas.add(new Byte("deviceId", "小车对应设备号"));
        baseDatas.add(new Byte("life", "心跳、指令、任务共用，没发一帧数据+1,0-255循环，res收到后原数据返回"));
        baseDatas.add(new Bit(4, "frameType", "报文类型"));
        baseDatas.add(new Bit(4, "version", "版本号"));
        baseDatas.add(new Byte("taskNo", "任务序号"));
        switch (rgvTaskMessageType) {
            case NORMAL_TASK_MESSAGE:
                generalNormalMessage(rgv, moveOrder);
                break;
            case EXTERN_TASK_NODE_MESSAGE:
                generalExTaskNodeMessage(rgv, moveOrder);
                break;
            case EX_TASK_NODE_WITH_SPEED_MSG:
                generalExTaskNoWithSpeedMsg(rgv, moveOrder);
                break;
            default:
                throw new RuntimeException("任务报文类型配置错误，请查看application中rgv-rgvTaskMessageType配置是否正确");
        }
        baseDatas.add(new Word("msgLen", "长度"));
        baseDatas.add(new Word("CRC16", "CRC检验位"));
        baseDatas.add(new Word("endFrame", "报文尾帧：03 fc"));

        setDefaultValue();
        setValue("frameType", RgvMessageType.RGV_TASK_MESSAGE.getValue());
        setValue("taskNo", moveOrder.getTaskNo());
        setValue("segmentNo", moveOrder.getSegmentNo());
    }

    private void generalNormalMessage(Rgv rgv, MoveOrder moveOrder) {
        baseDatas.add(new Byte("segmentNo", "段总数"));
        for (int i = 1; i <= nodes.size(); i++) {
            baseDatas.add(new Byte("X" + i, "X坐标"));
            baseDatas.add(new Byte("Y" + i, "Y坐标"));
            baseDatas.add(new Byte("Z" + i, "Z坐标"));
            baseDatas.add(new Byte("action" + i, "动作"));

            setValue("X" + i, nodes.get(i - 1).getX());
            setValue("Y" + i, nodes.get(i - 1).getY());
            setValue("Z" + i, nodes.get(i - 1).getZ());
            int resAction = 0;
            if (nodes.get(i - 1).getResAction() != null) {
                resAction = getActionValue(nodes.get(i - 1).getResAction());
            }
            setValue("action" + i, resAction);
        }
    }

    private void generalExTaskNodeMessage(Rgv rgv, MoveOrder moveOrder) {
        baseDatas.add(new Word("segmentNo", "段总数"));
        for (int i = 1; i <= nodes.size(); i++) {
            baseDatas.add(new Byte("X" + i, "X坐标"));
            baseDatas.add(new Byte("Y" + i, "Y坐标"));
            baseDatas.add(new Byte("Z" + i, "Z坐标"));
            baseDatas.add(new Byte("action" + i, "动作"));

            setValue("X" + i, nodes.get(i - 1).getX());
            setValue("Y" + i, nodes.get(i - 1).getY());
            setValue("Z" + i, nodes.get(i - 1).getZ());
            int resAction = 0;
            if (nodes.get(i - 1).getResAction() != null) {
                resAction = getActionValue(nodes.get(i - 1).getResAction());
            }
            setValue("action" + i, resAction);
        }
    }

    private void generalExTaskNoWithSpeedMsg(Rgv rgv, MoveOrder moveOrder) {
        baseDatas.add(new Word("segmentNo", "段总数"));
        for (int i = 1; i <= nodes.size(); i++) {
            baseDatas.add(new Byte("X" + i, "X坐标"));
            baseDatas.add(new Byte("Y" + i, "Y坐标"));
            baseDatas.add(new Byte("Z" + i, "Z坐标"));
            baseDatas.add(new Byte("action" + i, "动作"));
            baseDatas.add(new Word("speed"+i, "速度"));

            setValue("X" + i, nodes.get(i - 1).getX());
            setValue("Y" + i, nodes.get(i - 1).getY());
            setValue("Z" + i, nodes.get(i - 1).getZ());
            setValue("speed" + i, nodes.get(i - 1).getSpeed());
            int resAction = 0;
            if (nodes.get(i - 1).getResAction() != null) {
                resAction = getActionValue(nodes.get(i - 1).getResAction());
            }
            setValue("action" + i, resAction);
        }
    }

    private int getActionValue(Action action) {
        switch (action) {
            case PALLET_UP:
                return Order.PALLET_UP.getOrderByte();
            case PALLET_DOWN:
                return Order.PALLET_DOWN.getOrderByte();
            case CHANGE_TO_RAMP:
                return Order.CHANGE_TO_RAMP.getOrderByte();
            case CHANGE_TO_ROADWAY:
                return Order.CHANGE_TO_ROADWAY.getOrderByte();
            default:
                LoggerUtil.warn("目前不支持的节点指令:" + action, this.getClass());
                return 0;
        }
    }

    public int getTaskNo() {
        return getValue("taskNo");
    }

    public int getTaskType() {
        return getValue("报文类型");
    }

    public int getSegmentNo() {
        return getValue("segmentNo");
    }

    protected void setCrc(int crc) {
        setValue("CRC16", crc);
    }

    protected void setLength(int length) {
        setValue("msgLen", length);
    }

    public void analyzeTaskMessage() {
        Rgv rgv = getRgv();
        RgvTaskAction action = rgv.getTaskAction();
        RgvCommandAction cmdAction = rgv.getCmdAction();
        if (action.getActionStatus() != RgvActionStatus.RGV_NONE_ACTION) {
            if (cmdAction.getActionType().getOrderByte() == Order.INITIALIZE.getOrderByte()) {
                action.setActionNo(this.getTaskNo());
                return;
            }
            if (action.getActionNo() == this.getTaskNo()
                    && action.getMaxSegmentNo() == this.getSegmentNo()) {
                return;
            }
            throw new SendMessageException(rgv.getRgvName() + "当前有任务没有完成，任务ID:"
                    + action.getActionNo() + ",任务状态:" + action.getActionStatus().getDes());
        }

        action.setActionNo(getTaskNo());
        action.setMaxSegmentNo(getSegmentNo());
        action.setActionStatus(RgvActionStatus.RGV_WAITING_ACTION);

        StringBuffer sb = new StringBuffer();

        nodes.forEach(node -> {
            sb.append(node.getDes() + ",");
        });

        LoggerUtil.info(rgv.getRgvName() + "发送整体任务:" + sb.toString(), this.getClass());
    }

    @Override
    public Integer getMessageLife() {
        return getValue("life");
    }

    @Override
    public Integer getMessageType() {
        return getValue("frameType");
    }
}
